package com.lwl;

import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;

import java.util.ArrayList;
import java.util.List;

/**
 * @author liuweilong
 * @date 2021/3/11
 * @description
 */
@Slf4j
public class RedisUtils {
    private StringRedisTemplate redisTemplate;
    /**
     * keys: userIds对应的key，先删除后增加
     * argv1 : oldUrl    argv2: newUrl   argv3: 过期时间，秒
     */
    protected static final String DELETE_AND_REPLACE_WITH_NEW_URL_ACCESS_CACHE =
            "for i = 1, #(KEYS) do " +
                    "redis.call('srem', KEYS[i], ARGV[1]);" +
                    "redis.call('sadd', KEYS[i], ARGV[2]);" +
                    "redis.call('expire', KEYS[i], ARGV[3]);" +
                    "end;";

    /**
     * key1: 菜单set   key2: 用户权限key
     * argv1: 要查询的url
     */
    private static final String HAS_AUTH =
            "local existedInMenuSet = redis.call('sismember', KEYS[1], ARGV[1]);" +
                    "if(existedInMenuSet == 0) " +
                    "then return 1;end;" +
                    "return redis.call('sismember', KEYS[2], ARGV[1]);";


    /**
     * 监听订阅事件
     *
     * @param csRedisConnectionFactory
     * @return
     */
    public RedisMessageListenerContainer ceContainer(@Qualifier("csRedisConnectionFactory") RedisConnectionFactory csRedisConnectionFactory) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(csRedisConnectionFactory);
        MessageListenerAdapter menuAuthSwitchAdapter = new MessageListenerAdapter((Receiver) message -> {
            log.info("接收到消息，回调receiveMessage");
        }, "receiveMessage");
        menuAuthSwitchAdapter.afterPropertiesSet();
        container.addMessageListener(menuAuthSwitchAdapter, new PatternTopic("my.topic"));
        return container;
    }

    public interface Receiver {
        void receiveMessage(String message);
    }

    /**
     * 发布事件
     *
     * @param topic
     * @param msg
     */
    public void publish(String topic, String msg) {
        redisTemplate.convertAndSend(topic, msg);
    }

    /**
     * 执行lua脚本
     *
     * @param script
     * @param expectedResultType
     * @param keys
     * @param args
     * @param <T>
     * @return
     */
    public <T> T execScript(String script, Class<T> expectedResultType, List<String> keys, String... args) {
        DefaultRedisScript<T> redisScript = new DefaultRedisScript<>();
        redisScript.setScriptText(script);
        redisScript.setResultType(expectedResultType);
        //只能用秒，而且必须转换为字符串

        return redisTemplate.execute(redisScript, keys, args);
    }

    public static void main(String[] args) {
        //argv1 : oldUrl    argv2: newUrl   argv3: 过期时间，秒
        ArrayList<String> keys = new ArrayList<>();
        keys.add("key1");
        RedisUtils redisUtils = new RedisUtils();
        redisUtils.execScript(DELETE_AND_REPLACE_WITH_NEW_URL_ACCESS_CACHE, Void.class, keys, "arg1", "arg2"
                , "10");


        Long result = redisUtils.execScript(HAS_AUTH, Long.class, Lists.newArrayList("key1", "key2"), "arg1");
        boolean exist = result == 1L;
    }
}
